#ifndef _IOS14443A_C_
#define _IOS14443A_C_
/**
 ****************************************************************
 * @file iso14443a.c
 *
 * @brief  iso1443a protocol driver
 *
 * @author
 *
 *
 ****************************************************************
 */

/*
 * INCLUDE FILES
 ****************************************************************
 */
#include "include/zkrd522.h"
#include "include/iso14443a.h"
#include "include/spi.h"
/**
 ****************************************************************
 * @brief pcd_request()
 *
 * 功    能：寻卡
 *
 * @param: req_code[IN]:寻卡方式
 *                0x52 = 寻感应区内所有符合14443A标准的卡
 *                0x26 = 寻未进入休眠状态的卡
 * @param: ptagtype[OUT]：卡片类型代码
 *                0x4400 = Mifare_UltraLight
 *                0x4400 = Mifare_One(S50_0)
 *                0x0400 = Mifare_One(S50_3)
 *                0x0200 = Mifare_One(S70_0)
                  0x4200 = Mifare_One(S70_3)
 *                0x0800 = Mifare_Pro
 *                0x0403 = Mifare_ProX
 *                0x4403 = Mifare_DESFire
 *
 * @return: 成功返回MI_OK
 * @retval:
 ****************************************************************
 */
char pcd_request(unsigned char req_code, unsigned char *ptagtype)
{
    char status;
    transceive_buffer mf_com_data;
    transceive_buffer  *pi;
    pi = &mf_com_data;

    #if (NFC_DEBUG)
    uart_printf("REQA/WUPA >> ");
    #endif
    spi_write_reg(command_reg, PCD_M1STOP | BIT7);//command寄存器最高位需置1
    spi_write_reg(snd_byte_num_reg, 0x00);                   //0byte
    spi_write_reg(snd_bit_num_reg, 0x07); // Tx last bytes = 7

    clear_bit_mask(txmode_reg, BIT7); //不使能发送crc
    clear_bit_mask(rxmode_reg, BIT7); //不使能接收crc
    clear_bit_mask(status2_reg, BIT3);//清零MF crypto1认证成功标记

    mf_com_data.mf_command = PCD_TRANSCEIVE;
    mf_com_data.mf_length = 1;
    mf_com_data.mf_data[0] = req_code;

    status = pcd_com_transceive(pi);
    if(!status && mf_com_data.mf_length != 0x02)
    {
        status = MI_BYTECOUNTERR;
    }

    *ptagtype = mf_com_data.mf_data[0];
    *(ptagtype + 1) = mf_com_data.mf_data[1];

    #if (NFC_DEBUG)
    uart_printf("status = %d\r\n", status);
    #endif

    return status;
}
/**
 ****************************************************************
 * @brief pcd_anticoll()
 *
 * 防冲撞函数
 * @param: select_code    0x93  cascaded level 1
 *                        0x95  cascaded level 2
 *                        0x97  cascaded level 3
 * @param: uid 存放序列号(4byte)的内存单元首地址
 * @return: status 值为MI_OK:成功
 * @retval: uid  得到的序列号放入指定单元
 ****************************************************************
 */
char pcd_anticoll(unsigned char sel_code, unsigned char *uid)
{
	char status;
	unsigned char i = 0;
	unsigned char coll_byte_pos = 0;        													//冲突出现的字节位置
	unsigned char coll_bit_pos = 0;         													//冲突出现的bit位置                 													//接收状态寄存器三种标志
	unsigned char snr[5];          													//发完93+20，有冲突，读完所有FIFO数据回来
	unsigned char temp;
	unsigned char bytes = 2,send_byte_num = 2;        													//发送字节数，nvb高4位
	unsigned char send_bit_num = 0;         													//发送的bit数，nvb低4位
	unsigned char rec_begin_bit_pos = 0;    													//从哪位开始作为一字节
	

	transceive_buffer  mf_com_data;
	transceive_buffer  *pi;
	pi = &mf_com_data;
	memset(snr, 0, sizeof(snr));
	#if NFC_DEBUG
	uart_printf("Anticoll >> ");
	#endif
	do
	{
		spi_write_reg(rec_begin_bit_pos_reg, rec_begin_bit_pos);   //配置开始接收位寄存器
		mf_com_data.mf_command = PCD_TRANSCEIVE;
		mf_com_data.mf_length = bytes;
		mf_com_data.mf_data[0] = sel_code;							//sel
		mf_com_data.mf_data[1] = ((send_byte_num & 0x0F) << 4) | (send_bit_num & 0x0f);//NVB
		spi_write_reg(snd_byte_num_reg, send_byte_num);                     //2bytes
		spi_write_reg(snd_bit_num_reg, send_bit_num);    
		for(i = 0; i <=(coll_byte_pos); i++)
		{
			mf_com_data.mf_data[2 + i] = snr[i];//组装要发送的字节内容
		}
		status = pcd_com_transceive(pi);

		temp = snr[coll_byte_pos];//保存冲突字节的有效位
		if(status == MI_COLL)
		{
				#if (NFC_DEBUG)
				uart_printf("coll\r\n");
				#endif
				mf_com_data.mf_data[1] |= temp;//整合

				coll_byte_pos = mf_com_data.mf_data[0] >> 4;
				coll_bit_pos  = mf_com_data.mf_data[0]  & 0x0f;
				#if (NFC_DEBUG)
				uart_printf("coll_bit_pos is:%02x\r\n", coll_bit_pos);
				uart_printf("coll_byte_pos is:%02x\r\n", coll_byte_pos);
				uart_printf("Coll orrcur\r\n");
				#endif

				if(coll_bit_pos == 7)
				{
						send_byte_num     = send_byte_num + coll_byte_pos + 1;
						send_bit_num      = 0;
						rec_begin_bit_pos = 0;
						bytes = send_byte_num;
				}
				else
				{
						send_byte_num  = send_byte_num + coll_byte_pos;
						send_bit_num   = coll_bit_pos + 1;
						rec_begin_bit_pos = coll_bit_pos + 1;
						bytes = (send_byte_num+1);
				}

				for(i = 0; (5 >= coll_byte_pos) && (i < coll_byte_pos); i++)
				{
						snr[i] = mf_com_data.mf_data[i + 1];//获取冲突前的字节
				}
			 snr[coll_byte_pos] = (mf_com_data.mf_data[coll_byte_pos + 1] & ~(0xFF << coll_bit_pos)) + (1 << coll_bit_pos); //组合冲突位字节内容
		}
		else if(MI_OK == status)
		{	
			for(i=0; i < mf_com_data.mf_length && (i <= 4); i++)  //增加(i <= 4)防止snr[4-i]溢出
			{
					snr[4-i] = mf_com_data.mf_data[mf_com_data.mf_length-i-1];
			}
			snr[coll_byte_pos] |= temp;//组合之前接收到的有效比特
		}
  }while(MI_COLL == status);
	spi_write_reg(rec_begin_bit_pos_reg, 0);
	if(status == MI_OK)
	{
			for(i = 0; i < 4; i++)
			{
					uid[i] = snr[i];
			}

			#if (NFC_DEBUG)
			uart_printf("UID = ");

			for(i = 0; i < 4; i++)
			{
				uart_printf("%02x ", uid[i]);
			}

			uart_printf("\r\n");
			#endif
			//spi_write_reg(rec_begin_bit_pos_reg, 0);   //配置开始接收位寄存器,恢复默认接收起始位置
			return MI_OK;
	}
	else
	{
//		spi_write_reg(rec_begin_bit_pos_reg, 0);
		return MI_COLLERR;
	}
}

/**
 ****************************************************************
 * @brief pcd_select()
 *
 * 选定一张卡
 * @param: select_code    0x93  cascaded level 1
 *                        0x95  cascaded level 2
 *                        0x97  cascaded level 3
 * @param: psnr 存放序列号(4byte)的内存单元首地址
 * @return: status 值为MI_OK:成功
 * @retval: psnr  得到的序列号放入指定单元
 * @retval: psak  得到的Select acknolege 回复
 *
 *            sak:
 *            Corresponding to the specification in ISO 14443, this function
 *            is able to handle extended serial numbers. Therefore more than
 *            one select_code is possible.
 *
 *            Select codes:
 *
 *            +----+----+----+----+----+----+----+----+
 *            | b8 | b7 | b6 | b5 | b4 | b3 | b2 | b1 |
 *            +-|--+-|--+-|--+-|--+----+----+----+-|--+
 *              |    |    |    |  |              | |
 *                                |              |
 *              1    0    0    1  | 001..std     | 1..bit frame anticoll
 *                                | 010..double  |
 *                                | 011..triple  |
 *
 *            SAK:
 *
 *            +----+----+----+----+----+----+----+----+
 *            | b8 | b7 | b6 | b5 | b4 | b3 | b2 | b1 |
 *            +-|--+-|--+-|--+-|--+-|--+-|--+-|--+-|--+
 *              |    |    |    |    |    |    |    |
 *                        |              |
 *                RFU     |      RFU     |      RFU
 *
 *                        1              0 .. UID complete, ATS available
 *                        0              0 .. UID complete, ATS not available
 *                        X              1 .. UID not complete
 *
 ****************************************************************
 */
char pcd_select(unsigned char  select_code, unsigned char  *psnr, unsigned char  *psak)
{
    unsigned char  i;
    char  status;
    unsigned char  snr_check;
    unsigned char  crc_lsb = 0;
    unsigned char  crc_msb = 0;
    transceive_buffer  mf_com_data;
    transceive_buffer  *pi;
    pi = &mf_com_data;
    snr_check = 0;
    #if (NFC_DEBUG)
    uart_printf("SELECT >>");
    #endif
    spi_write_reg(recstate_reg, 0x7F);                       //清除寄存器
    spi_write_reg(fifolevel_reg, 0x80);                     //clear fifo data
    spi_write_reg(snd_byte_num_reg, 0x09);                   //0byte
    spi_write_reg(snd_bit_num_reg, 0x00); //
    clear_bit_mask(txmode_reg, BIT7); //不使能发送crc
    clear_bit_mask(rxmode_reg, BIT7); //不使能接收crc

    mf_com_data.mf_command = PCD_TRANSCEIVE;
    mf_com_data.mf_length = 9;
    mf_com_data.mf_data[0] = select_code;
    mf_com_data.mf_data[1] = 0x70;

    for(i = 0; i < 4; i++)
    {
        snr_check ^= *(psnr + i);
        mf_com_data.mf_data[i + 2] = *(psnr + i);
    }

    mf_com_data.mf_data[6] = snr_check;
    pcd_get_crc(CRC_A, 7, mf_com_data.mf_data, &crc_lsb, &crc_msb);
    mf_com_data.mf_data[7] = crc_lsb;
    mf_com_data.mf_data[8] = crc_msb;
    status = pcd_com_transceive(pi);

    if(status == MI_OK)
    {
        if(mf_com_data.mf_length != 0x3)//含crc两字节
        {
            status = MI_BYTECOUNTERR;
        }
        else
        {
            *psak = mf_com_data.mf_data[0];
        }
    }

    #if (NFC_DEBUG)
    uart_printf("status = %x\r\n", status);
    #endif
    return status;
}

/**
 ****************************************************************
 * @brief pcd_hlta()
 *
 * 功能：命令卡进入休眠状态
 *
 * @param:
 * @return: status 值为MI_OK:成功
 *
 ****************************************************************
 */
char pcd_halt(void)
{
    unsigned char crc_lsb = 0;
    unsigned char crc_msb = 0;
    int status = MI_OK;
    transceive_buffer  mf_com_data;
    transceive_buffer  *pi;
    pi = &mf_com_data;

    #if (NFC_DEBUG)
    uart_printf("HALT:");
    #endif
    spi_write_reg(fifolevel_reg, 0x80);        							//clear fifo data
    spi_write_reg(recstate_reg, 0x7f);
    spi_write_reg(snd_byte_num_reg, 0x04);                     			//4bytes
    spi_write_reg(snd_bit_num_reg, 0x00);                      			//0byte

    mf_com_data.mf_command = PCD_TRANSMIT;
    mf_com_data.mf_length  = 4;
    mf_com_data.mf_data[0] = PICC_HLTA;
    mf_com_data.mf_data[1] = 0;
    pcd_get_crc(CRC_A, 2, mf_com_data.mf_data, &crc_lsb, &crc_msb);
    mf_com_data.mf_data[2] = crc_lsb;
    mf_com_data.mf_data[3] = crc_msb;

    status = pcd_com_transceive(pi);

    #if (NFC_DEBUG)
    uart_printf("status = 0x%x\r\n", status);
    #endif
    return status;
}
 #endif
 